package com.seashell.appstartupjob.listener;

import java.io.File;
import java.net.URL;
import java.util.List;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import com.seashell.appstartupjob.config.parser.JobConfigurationRootParser;
import com.seashell.appstartupjob.exceptions.JobConfigNotCorrectException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.seashell.appstartupjob.job.AbstractJarRefJob;
import com.seashell.appstartupjob.job.AbstractServletJob;
import com.seashell.appstartupjob.job.IJob;

/**
 * com.seashell.appstartupjob.listener.AbstractApplicationStartupListener
 * 系统启动前执行任务监听器
 *
 * @author Allen
 * @version v1.0
 * @date 2017/7/14
 */
public abstract class AbstractApplicationStartupListener implements ServletContextListener {

    private static Logger logger = LoggerFactory.getLogger(AbstractApplicationStartupListener.class);

    /**
     * 默认配置文件位置
     */
    private static final String DEFAULT_CONFIG_FILE = "application-start-up.xml";

    @Override
    public void contextInitialized(ServletContextEvent event) {

        /**
         * 获取配置文件地址，如果获取为空，则使用默认地址
         */
        String configFilePath = getConfigFilePath();
        if(StringUtils.isEmpty(configFilePath)){
            configFilePath = DEFAULT_CONFIG_FILE;
        }
       // configFilePath = event.getServletContext().getRealPath("") + configFilePath;

        URL resource = this.getClass().getClassLoader().getResource(configFilePath);

        File configFile = new File(resource.getFile());
        if(!configFile.exists()){
            throw new JobConfigNotCorrectException("配置文件未找到");
        }
        /**
         * 解析配置文件
         */
        List<IJob> jobs;
        try {
            jobs = new JobConfigurationRootParser().parse(configFile);
        } catch (JobConfigNotCorrectException e) {
            logger.error("解析配置文件出错," + e.getMessage());
            throw e;
        }

        StringBuilder jobNames = new StringBuilder();
        for (IJob job : jobs) {
            jobNames.append(job.getJobName()).append(",");
        }
        logger.info("准备执行启动前任务：{}",jobNames.toString());

        /**
         * 触发执行前事件
         */
        onBeforeJobsExcuted(event,jobs);

        /**
         * 执行任务
         */
        for (IJob job : jobs) {
            /**
             * 如果是Servlet类工作，将servlet的context加进job
             */
            if(AbstractServletJob.class.isAssignableFrom(job.getClass())){
                ((AbstractServletJob)job).setServletContext(event.getServletContext());
            }
            if(AbstractJarRefJob.class.isAssignableFrom(job.getClass())){
                ((AbstractJarRefJob)job).setJarRefClass(this.getClass());
            }

            onBeforeEachJobExcuted(event,job);
            job.doJob();
            onAfterEachJobExcuted(event,job);
        }

        /**
         * 触发执行后时间
         */
        onAfterJobsExcuted(event,jobs);

        logger.info("已完成执行系统启动前任务");

    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }

    /**
     * 获取配置文件地址
     * @return
     */
    protected abstract String getConfigFilePath();

    /**
     * 所有Job执行前触发
     * @param servletContextEvent
     * @param jobs
     */
    protected abstract void onBeforeJobsExcuted(ServletContextEvent servletContextEvent, List<IJob> jobs);

    /**
     * 每个Job执行前触发
     * @param servletContextEvent
     * @param jobs
     */
    protected abstract void onBeforeEachJobExcuted(ServletContextEvent servletContextEvent, IJob jobs);

    /**
     * 每个Job执行完后触发
     * @param servletContextEvent
     * @param job
     */
    protected abstract void onAfterEachJobExcuted(ServletContextEvent servletContextEvent,IJob job);

    /**
     * 所有Job执行完后触发
     * @param servletContextEvent
     * @param jobs
     */
    protected abstract void onAfterJobsExcuted(ServletContextEvent servletContextEvent, List<IJob> jobs);
}
